package com.techwells.heartfelt.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.text.NumberFormat;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.PropertyUtilsBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.techwells.heartfelt.dao.entity.BaseEntity;
import com.techwells.heartfelt.viewobject.BaseViewObject;
import com.techwells.heartfelt.viewobject.HeartfeltBaseViewObject;

/**
 * Grape工具类
 * 
 * @author 马蹄声
 * @version 1.0
 *
 */
public final class HeartfeltBizUtils {
    
    private static final Logger logger = 
            LoggerFactory.getLogger( HeartfeltBizUtils.class );

    public static void copyProperties( Object dest, Object orig ) {
        
        if( dest == null || orig == null ) {
            return;
        }
        
        try {
            
            HeartfeltDAOUtils.copyProperties( dest, orig );
            
            /*
              when view -> entity, then vid -> id;
              when entity -> view, then id -> vid
            */
            if( dest instanceof HeartfeltBaseViewObject 
                    && orig instanceof BaseEntity ) {
                copyProperty( dest, "vid", orig, "id" );
            }else if( dest instanceof BaseEntity 
                    && orig  instanceof HeartfeltBaseViewObject ) {
                copyProperty( dest, "id", orig, "vid" );
            }
            
            if( dest instanceof BaseViewObject ) {
                transNullToEmptyString( dest );
            }
            
        } catch ( Exception ex ) {
            throw new IllegalArgumentException( ex );
        }
    }
    
    public static boolean copyProperty( Object dest, 
            String destFieldName,
            Object orig,
            String origFieldName ) {
        
        boolean b = false;
        
        PropertyUtilsBean propertyUtils = BeanUtilsBean.getInstance()
                .getPropertyUtils();
        
        Object origValue;
        try {
            origValue = propertyUtils.getProperty( orig, origFieldName );
            
            /* 
             * verify if dest object does take the field 
             * of name "destFieldName"
             */
            propertyUtils.getProperty( dest, destFieldName );
            
            Class<?> destPropertyClass = 
                    propertyUtils.getPropertyType( dest, destFieldName );
            
            if( origValue == null && destPropertyClass != null
                    && String.class.isAssignableFrom( destPropertyClass ) ) {
                origValue = "";
            }
            
            propertyUtils.setProperty( dest, destFieldName, origValue );
            
            b = true;
            
        }catch( Exception ex ) {
//            logger.error( "copy property failed: " 
//                    + "origFieldName = " + origFieldName 
//                    + ", destFieldName = " + destFieldName
//                    , ex );
        }
        
        return b;
    }
    
    public static void transNullToEmptyString( Object target ) {
        if( target == null ) {
            return;
        }
        PropertyUtilsBean propertyUtils = BeanUtilsBean.getInstance()
                .getPropertyUtils();
        
        PropertyDescriptor[] descriptors = 
                propertyUtils.getPropertyDescriptors( target );
        try {
            if( descriptors != null ) {
                for( PropertyDescriptor desc : descriptors ) {
                    if( String.class.isAssignableFrom( desc.getPropertyType() ) ) {
                        Method readMethod = desc.getReadMethod();
                        Object value = readMethod.invoke( target );
                        if( value == null ) {
                            Method method = desc.getWriteMethod();
                            method.invoke( target, "" );
                        }
                    }
                }
            }
        }catch( Exception ex ) {
            logger.error( "GrapeBizUtils.transNullToEmptyString exception", ex );
        }
    }
    
    public static String asString( boolean b ) {
        return b ? Constants.BOOLEAN_TRUE_IN_STR 
                : Constants.BOOLEAN_FALSE_IN_STR;
    }
    
    public static String asString( int value ) {
        return String.valueOf( value );
    }
    
    public static String asString( float value ) {
//        NumberFormat numberFormat = NumberFormat.getInstance();
//        numberFormat.setMaximumFractionDigits( 1 );
        return String.valueOf( value );
    }
    
    public static String discountToStr( Float f ) {
        if( f != null ) {
            NumberFormat numberFormat = NumberFormat.getInstance();
            numberFormat.setMaximumFractionDigits( 2 );
            String s = numberFormat.format( f );
            int idx = s.lastIndexOf( "." );
            if( idx <= 0 ) {
                return s;
            }
            String suffix = s.substring( idx );
            if( "00".equals( suffix ) || "0".equals( suffix ) ) {
                return s.substring( 0, idx );
            }else {
                return s;
            }
        }
        return "1";
    }

    // hide from initiating
    private HeartfeltBizUtils() {}
    
    
    public static double ratio( int lastValue, int currentValue, int periodValue ) {
        
        if( lastValue < 0 ) {
            throw new IllegalArgumentException( 
                    "Argument lastValue is less than 0!!" );
        }
        
        if( currentValue <= 0 ) {
            throw new IllegalArgumentException( 
                    "Argument currentValue is less than or equals to 0!!" );
        }
        
        if( periodValue <= 0 ) {
            throw new IllegalArgumentException( 
                    "Argument periodValue is less than or equals to 0!!" );
        }
        
        int deltaValue = currentValue - lastValue;
        
        if( deltaValue < 0 ) {
            throw new IllegalArgumentException( 
                 "Argument currentValue should be greater than lastValue!!" );
        }
        
        
        if( deltaValue == 0 ) {
            return 0;
        }
        
        double dCurrentValue = deltaValue - 0.000001;
        
        return ( dCurrentValue % periodValue ) / periodValue;

    }
}
